/*
 *Copyright (c) 2024 Black Sesame Technologies
 *
 *Licensed under the Apache License, Version 2.0 (the "License");
 *you may not use this file except in compliance with the License.
 *You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 *Unless required by applicable law or agreed to in writing, software
 *distributed under the License is distributed on an "AS IS" BASIS,
 *WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *See the License for the specific language governing permissions and
 *limitations under the License.
*/

#ifndef __HSCG_FIRMWARE_PACKET_STATISTIC_H__
#define __HSCG_FIRMWARE_PACKET_STATISTIC_H__
#include "types.h"

/**************************** Statistics packet timestamp information related function START *****************************/
#ifdef STATISTICS_PACKET_TIMESTAMP_ENABLE

#define STATISTICS_PACKET_USE_GMAC_PHC_TIMESTAMP

#define STATISTICS_PACKET_TIMESTAMP_GRPNUM 1024
#define TIMESTAMP_PACKET_NUM 16
#define STATISTICS_PACKET_DATA_SIZE 8

#ifdef STATISTICS_PACKET_CAN2ETH_TIMESTAMP_ENABLE
enum statistics_packet_can2eth_timestamp_step {
    TIMESTAMP_PACKET_CAN2ETH_HW_RECV_CAN_PACKET = 0,
    TIMESTAMP_PACKET_CAN2ETH_SW_RECV_CAN_PACKET,
    TIMESTAMP_PACKET_CAN2ETH_WR_CAN2ETH_SQBUF_START
};
#endif

#ifdef STATISTICS_PACKET_ETH2CAN_TIMESTAMP_ENABLE
enum statistics_packet_eth2can_timestamp_step {
    TIMESTAMP_PACKET_ETH2CAN_RECV_SQBUFFER = 0,
    TIMESTAMP_PACKET_ETH2CAN_SENDTO_CAN_CONTROLLER_START,
    TIMESTAMP_PACKET_ETH2CAN_SENDTO_CAN_CONTROLLER_END,
};
#endif

#ifdef STATISTICS_PACKET_CAN2CAN_TIMESTAMP_ENABLE
enum statistics_packet_can2can_timestamp_step {
    TIMESTAMP_PACKET_CAN2CAN_HW_RECV_CAN_PACKET = 0,
    TIMESTAMP_PACKET_CAN2CAN_SW_RECV_CAN_PACKET,
    TIMESTAMP_PACKET_CAN2CAN_SENDTO_CAN_CONTROLLER_START,
    TIMESTAMP_PACKET_CAN2CAN_SENDTO_CAN_CONTROLLER_END
};
#endif

struct statistics_packet_timestamp_t {
    uint64 timestamp[TIMESTAMP_PACKET_NUM];
    uint8 data[STATISTICS_PACKET_DATA_SIZE];
    uint32 id;
};

extern struct statistics_packet_timestamp_t *statistics_packet_timestamp;

#define STATISTICS_UPDATE_PACKET_TIMESTAMP(step_inx) statistics_packet_timestamps_update(step_inx)

#define STATISTICS_UPDATE_PACKET_TIMESTAMP_BY_VAULE(step_inx, value)                                                                   \
    do {                                                                                                               \
        if (step_inx >= TIMESTAMP_PACKET_NUM)                                                                                 \
            statistics->packet_timestamp_step = 0;                                                                     \
        else                                                                                                           \
            statistics->packet_timestamp_step = step_inx;                                                              \
        statistics_packet_timestamp[statistics->packet_timestamp_loop].timestamp[statistics->packet_timestamp_step] =         \
            value;                                                                                     \
    } while (0)

#define STATISTICS_UPDATE_PACKET_DATA(id, data, len) statistics_packet_data_update(id, data, len)
#define STATISTICS_UPDATE_PACKET_LOOP() statistics_packet_loop_inc()

#else

#define STATISTICS_UPDATE_PACKET_TIMESTAMP(step_inx)
#define STATISTICS_UPDATE_PACKET_TIMESTAMP_BY_VAULE(step_inx, value)
#define STATISTICS_UPDATE_PACKET_DATA(id, data, len)
#define STATISTICS_UPDATE_PACKET_LOOP()
#endif /* STATISTICS_PACKET_TIMESTAMP_ENABLE */

#ifdef STATISTICS_PACKET_CAN2ETH_TIMESTAMP_ENABLE
#define STATISTICS_UPDATE_PACKET_CAN2ETH_TIMESTAMP(step_inx) STATISTICS_UPDATE_PACKET_TIMESTAMP(step_inx)
#define STATISTICS_UPDATE_PACKET_CAN2ETH_TIMESTAMP_BY_VAULE(step_inx, value) STATISTICS_UPDATE_PACKET_TIMESTAMP_BY_VAULE(step_inx, value)
#define STATISTICS_UPDATE_PACKET_CAN2ETH_DATA(id, data, len) STATISTICS_UPDATE_PACKET_DATA(id, data, len)
#define STATISTICS_UPDATE_PACKET_CAN2ETH_LOOP() STATISTICS_UPDATE_PACKET_LOOP()
#else
#define STATISTICS_UPDATE_PACKET_CAN2ETH_TIMESTAMP(step_inx)
#define STATISTICS_UPDATE_PACKET_CAN2ETH_TIMESTAMP_BY_VAULE(step_inx, value)
#define STATISTICS_UPDATE_PACKET_CAN2ETH_DATA(id, data, len)
#define STATISTICS_UPDATE_PACKET_CAN2ETH_LOOP()
#endif /* STATISTICS_PACKET_CAN2ETH_TIMESTAMP_ENABLE */

#ifdef STATISTICS_PACKET_ETH2CAN_TIMESTAMP_ENABLE
#define STATISTICS_UPDATE_PACKET_ETH2CAN_TIMESTAMP(step_inx) STATISTICS_UPDATE_PACKET_TIMESTAMP(step_inx)
#define STATISTICS_UPDATE_PACKET_ETH2CAN_TIMESTAMP_BY_VAULE(step_inx, value) STATISTICS_UPDATE_PACKET_TIMESTAMP_BY_VAULE(step_inx, value)
#define STATISTICS_UPDATE_PACKET_ETH2CAN_DATA(id, data, len) STATISTICS_UPDATE_PACKET_DATA(id, data, len)
#define STATISTICS_UPDATE_PACKET_ETH2CAN_LOOP() STATISTICS_UPDATE_PACKET_LOOP()
#else
#define STATISTICS_UPDATE_PACKET_ETH2CAN_TIMESTAMP(step_inx)
#define STATISTICS_UPDATE_PACKET_ETH2CAN_TIMESTAMP_BY_VAULE(step_inx, value)
#define STATISTICS_UPDATE_PACKET_ETH2CAN_DATA(id, data, len)
#define STATISTICS_UPDATE_PACKET_ETH2CAN_LOOP()
#endif /* STATISTICS_PACKET_ETH2CAN_TIMESTAMP_ENABLE */

#ifdef STATISTICS_PACKET_CAN2CAN_TIMESTAMP_ENABLE
#define STATISTICS_UPDATE_PACKET_CAN2CAN_TIMESTAMP(step_inx) STATISTICS_UPDATE_PACKET_TIMESTAMP(step_inx)
#define STATISTICS_UPDATE_PACKET_CAN2CAN_TIMESTAMP_BY_VAULE(step_inx, value) STATISTICS_UPDATE_PACKET_TIMESTAMP_BY_VAULE(step_inx, value)
#define STATISTICS_UPDATE_PACKET_CAN2CAN_DATA(id, data, len) STATISTICS_UPDATE_PACKET_DATA(id, data, len)
#define STATISTICS_UPDATE_PACKET_CAN2CAN_LOOP() STATISTICS_UPDATE_PACKET_LOOP()
#else
#define STATISTICS_UPDATE_PACKET_CAN2CAN_TIMESTAMP(step_inx)
#define STATISTICS_UPDATE_PACKET_CAN2CAN_TIMESTAMP_BY_VAULE(step_inx, value)
#define STATISTICS_UPDATE_PACKET_CAN2CAN_DATA(id, data, len)
#define STATISTICS_UPDATE_PACKET_CAN2CAN_LOOP()
#endif /* STATISTICS_PACKET_CAN2CAN_TIMESTAMP_ENABLE */

#ifdef STATISTICS_PACKET_TIMESTAMP_ENABLE
void statistics_packet_timestamp_init(void);
void statistics_packet_loop_inc(void);
void statistics_packet_timestamps_update(uint32 step_inx);
void statistics_packet_data_update(uint32 id, uint8 *data, uint32 len);
#endif

#endif /* __HSCG_FIRMWARE_PACKET_STATISTIC_H__ */